/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "plugins/ecmascript/runtime/base/config.h"
#include "ic_runtime_stub.h"
#include "ic_handler.h"
#include "ic_runtime.h"
#include "profile_type_info.h"
#include "plugins/ecmascript/runtime/js_tagged_value-inl.h"
#include "plugins/ecmascript/runtime/js_array.h"
#include "plugins/ecmascript/runtime/js_hclass-inl.h"
#include "plugins/ecmascript/runtime/global_dictionary-inl.h"
#include "plugins/ecmascript/runtime/js_function.h"
#include "plugins/ecmascript/runtime/js_proxy.h"
#include "plugins/ecmascript/runtime/global_env.h"
#include "plugins/ecmascript/runtime/object_factory-inl.h"
#include "plugins/ecmascript/runtime/js_handle.h"
#include "plugins/ecmascript/runtime/interpreter/fast_runtime_stub-inl.h"
#include "plugins/ecmascript/runtime/ic/proto_change_details.h"

#include "plugins/ecmascript/runtime/vmstat/runtime_stat.h"
#include "plugins/ecmascript/runtime/runtime_call_id.h"

namespace ark::ecmascript {
JSTaggedValue ICRuntimeStub::LoadMissedICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
                                                JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId)
{
    INTERPRETER_TRACE(thread, LoadMissedICByName);
    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
    auto receiverHandle = JSHandle<JSTaggedValue>(thread, receiver);
    auto profileInfoHandle = JSHandle<ProfileTypeInfo>(thread, profileTypeInfo);
    LoadICRuntime icRuntime(thread, profileInfoHandle, slotId, ICKind::NAMED_LOAD_IC);
    return icRuntime.LoadMiss(receiverHandle, keyHandle);
}

JSTaggedValue ICRuntimeStub::LoadMissedICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
                                                 JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId)
{
    INTERPRETER_TRACE(thread, LoadMissedICByValue);

    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
    auto receiverHandle = JSHandle<JSTaggedValue>(thread, receiver);
    auto profileInfoHandle = JSHandle<JSTaggedValue>(thread, profileTypeInfo);
    LoadICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileInfoHandle), slotId, ICKind::LOAD_IC);
    return icRuntime.LoadMiss(receiverHandle, keyHandle);
}

JSTaggedValue ICRuntimeStub::StoreMissedICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
                                                  JSTaggedValue receiver, JSTaggedValue key, JSTaggedValue value,
                                                  uint32_t slotId)
{
    INTERPRETER_TRACE(thread, StoreMissedICByValue);

    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
    auto receiverHandle = JSHandle<JSTaggedValue>(thread, receiver);
    auto valueHandle = JSHandle<JSTaggedValue>(thread, value);
    auto profileInfoHandle = JSHandle<JSTaggedValue>(thread, profileTypeInfo);
    StoreICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileInfoHandle), slotId, ICKind::STORE_IC);
    return icRuntime.StoreMiss(receiverHandle, keyHandle, valueHandle);
}

JSTaggedValue ICRuntimeStub::StoreMissedICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
                                                 JSTaggedValue receiver, JSTaggedValue key, JSTaggedValue value,
                                                 uint32_t slotId)
{
    INTERPRETER_TRACE(thread, StoreMissedICByName);

    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
    auto receiverHandle = JSHandle<JSTaggedValue>(thread, receiver);
    auto valueHandle = JSHandle<JSTaggedValue>(thread, value);
    auto profileInfoHandle = JSHandle<JSTaggedValue>(thread, profileTypeInfo);
    StoreICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileInfoHandle), slotId,
                             ICKind::NAMED_STORE_IC);
    return icRuntime.StoreMiss(receiverHandle, keyHandle, valueHandle);
}

}  // namespace ark::ecmascript
